﻿using System;
using System.Collections.Generic;
using System.Text;
using RoverStudio.Common.PositionSource;
using System.Drawing;
using AForge.Imaging.Filters;

namespace Clustering
{
    public class KMeansClusteringVideoSeparator
    {
        private event NewFrameDelegate _frameGrabbed1; 
        private DelegateWrapperVideoSource _videoSource1;

        public IVideoSourceCommon VideoOutput1
        {
            get { return _videoSource1; }
        }
        
        private event NewFrameDelegate _frameGrabbed2;
        private DelegateWrapperVideoSource _videoSource2;

        public IVideoSourceCommon VideoOutput2
        {
            get { return _videoSource2; }
        }

        private LedPatternSeparator ledPatternSeparator;
        private AdaptiveThreshold adaptiveThreshold;
        //private ClusteringAlgorithm clusteringAlgorithm;
        private FiltersSequence filtersSequence;
        private bool initialized = false;

        public KMeansClusteringVideoSeparator(IVideoSourceCommon videoSource)
        {
            videoSource.NewFrame += new NewFrameDelegate(videoSource_FrameGrabbed);
            _videoSource1 = new DelegateWrapperVideoSource("Leds - Rover1", ref _frameGrabbed1);
            _videoSource2 = new DelegateWrapperVideoSource("Leds - Rover2", ref _frameGrabbed2);
            VideoSourceCommonInstancesHolder.SingletonInstance.Register(_videoSource1);
            VideoSourceCommonInstancesHolder.SingletonInstance.Register(_videoSource2);
        }
        
        ~KMeansClusteringVideoSeparator()
        {
            VideoSourceCommonInstancesHolder.SingletonInstance.UnRegister(_videoSource1);
            VideoSourceCommonInstancesHolder.SingletonInstance.UnRegister(_videoSource2);
        }


        public void Init(Bitmap background, Bitmap foreground)
        {
            ledPatternSeparator = new LedPatternSeparator(2);
            adaptiveThreshold = new AdaptiveThreshold(ledPatternSeparator, background, foreground);
            filtersSequence = adaptiveThreshold.GenerateFilterSequence();
 
            initialized = true;
        }

        public void Init()
        {
            ledPatternSeparator = new LedPatternSeparator(2);
            adaptiveThreshold = new AdaptiveThreshold(ledPatternSeparator, imgBackground, imgForeground);
            filtersSequence = adaptiveThreshold.GenerateFilterSequence();
            initialized = true;
        }

        void videoSource_FrameGrabbed(Bitmap frame)
        {
            if (setForeground)
            {
                setForeground = false;
                imgForeground = (Bitmap)frame.Clone();
            }
            if (setBackground)
            {
                setBackground = false;
                imgBackground = (Bitmap)frame.Clone();
            }
            if (!initialized)
                return;
            Bitmap filtered = this.filtersSequence.Apply(frame);
            Bitmap[] clusters = this.ledPatternSeparator.FindClusters(filtered);
            if (_frameGrabbed1 != null)
                _frameGrabbed1(clusters[0]);
            if (_frameGrabbed2 != null)
                _frameGrabbed2(clusters[1]);
        }




        public class DelegateWrapperVideoSource : IVideoSourceCommon
        {
            //private KMeansClusteringVideoSeparator parent;

            public DelegateWrapperVideoSource(string name, ref NewFrameDelegate sourceDelegate)
            {
                this.name = name;
                sourceDelegate += new NewFrameDelegate(OnFrameGrabbed);
            }

            private void OnFrameGrabbed(Bitmap frame)
            {
                if (NewFrame != null)
                    NewFrame(frame);
            }

            #region IVideoSourceCommon Members

            public event NewFrameDelegate NewFrame;
            private string name;
            public string Name
            {
                get { return name; }
            }

            public bool IsActive
            {
                get { throw new NotImplementedException(); }
            }

            #endregion
        }

        public void SwapRowers()
        {
            ledPatternSeparator.RotateClusters();
        }

        bool setBackground = false;
        bool setForeground = false;
        Bitmap imgBackground = null;
        Bitmap imgForeground = null;

        public void SetBackgroundNow()
        {
            setBackground = true;
        }
        public event EventHandler BackgroundSet;

        public void SetForegroundNow()
        {
            setForeground = true;
        }
        public event EventHandler ForegroundSet;


        public void SetBackground(Bitmap bmp)
        {
            imgBackground = bmp;
        }

        public void SetForeground(Bitmap bmp)
        {
            imgForeground = bmp;
        }
    }
}
